using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Xml;
using Common.Utilities;
using Common.Utilities.Dispatcher;
using PdfLib;

namespace Workflows.Components.TextMining.PdfBookmarkExtraction
{
    /// <summary></summary>
    [Serializable]
    public class PdfBookmarkExtractionInstruction:InstructionBase
    {
        #region src
        private string _SrcConnStr;
        /// <summary></summary>
        public string SrcConnStr
        {
            get
            {
                return this._SrcConnStr;
            }
            set
            {
                this._SrcConnStr = value;
            }
        }

        private string _SelectSql;
        /// <summary></summary>
        public string SelectSql
        {
            get
            {
                return this._SelectSql;
            }
            set
            {
                this._SelectSql = value;
            }
        }

        private string _FilePathField;
        /// <summary></summary>
        public string FilePathField
        {
            get
            {
                return this._FilePathField;
            }
            set
            {
                this._FilePathField = value;
            }
        }

        private string _SrcIDField;
        /// <summary></summary>
        public string SrcIDField
        {
            get
            {
                return this._SrcIDField;
            }
            set
            {
                this._SrcIDField = value;
            }
        }
        #endregion

        #region bookmark 
        private string _BookmarkTitle;
        /// <summary></summary>
        public string BookmarkTitle
        {
            get
            {
                return this._BookmarkTitle;
            }
            set
            {
                this._BookmarkTitle = value;
            }
        }

        private string _BookmarkPath;
        /// <summary></summary>
        public string BookmarkPath
        {
            get
            {
                return this._BookmarkPath;
            }
            set
            {
                this._BookmarkPath = value;
            }
        }

        private string[] _BookmarkSearchPatterns;
        /// <summary></summary>
        public string[] BookmarkSearchPatterns
        {
            get
            {
                return this._BookmarkSearchPatterns;
            }
            set
            {
                this._BookmarkSearchPatterns = value;
            }
        }

        private bool _AcrossMultipleBookmarks;
        /// <summary></summary>
        public bool AcrossMultipleBookmarks
        {
            get
            {
                return this._AcrossMultipleBookmarks;
            }
            set
            {
                this._AcrossMultipleBookmarks = value;
            }
        }

        private string _ToBookmarkTitle;
        /// <summary></summary>
        public string ToBookmarkTitle
        {
            get
            {
                return this._ToBookmarkTitle;
            }
            set
            {
                this._ToBookmarkTitle = value;
            }
        }

        private string _ToBookmarkPath;
        /// <summary></summary>
        public string ToBookmarkPath
        {
            get
            {
                return this._ToBookmarkPath;
            }
            set
            {
                this._ToBookmarkPath = value;
            }
        }

        private string[] _ToBookmarkPatterns;
        /// <summary></summary>
        public string[] ToBookmarkPatterns
        {
            get
            {
                return this._ToBookmarkPatterns;
            }
            set
            {
                this._ToBookmarkPatterns = value;
            }
        }
        #endregion

        #region filter 
        private List<PdfContentFilter> _ContentFilters;
        /// <summary></summary>
        public List<PdfContentFilter> ContentFilters
        {
            get
            {
                return this._ContentFilters;
            }
            set
            {
                this._ContentFilters = value;
            }
        }

        private bool _UseBoxedContent;
        /// <summary></summary>
        public bool UseBoxedContent
        {
            get
            {
                return this._UseBoxedContent;
            }
            set
            {
                this._UseBoxedContent = value;
            }
        }

        private float _MinWidth;
        /// <summary></summary>
        public float MinWidth
        {
            get
            {
                return this._MinWidth;
            }
            set
            {
                this._MinWidth = value;
            }
        }

        private float _MinHeight;
        /// <summary></summary>
        public float MinHeight
        {
            get
            {
                return this._MinHeight;
            }
            set
            {
                this._MinHeight = value;
            }
        }
        #endregion

        #region tgt 
        private string _TgtConnStr;
        /// <summary></summary>
        public string TgtConnStr
        {
            get
            {
                return this._TgtConnStr;
            }
            set
            {
                this._TgtConnStr = value;
            }
        }

        private string _TargetTableName;
        /// <summary></summary>
        public string TargetTableName
        {
            get { return _TargetTableName; }
            set { _TargetTableName = value; }
        }

        private string _TgtIDField;
        /// <summary></summary>
        public string TgtIDField
        {
            get
            {
                return this._TgtIDField;
            }
            set
            {
                this._TgtIDField = value;
            }
        }

        private string _BookmarkContentFieldName;
        /// <summary></summary>
        public string BookmarkContentFieldName
        {
            get
            {
                return this._BookmarkContentFieldName;
            }
            set
            {
                this._BookmarkContentFieldName = value;
            }
        }

        private string _ExtractFromPageField;
        /// <summary></summary>
        public string ExtractFromPageField
        {
            get
            {
                return this._ExtractFromPageField;
            }
            set
            {
                this._ExtractFromPageField = value;
            }
        }

        private string _ExtractFromPosField;
        /// <summary></summary>
        public string ExtractFromPosField
        {
            get
            {
                return this._ExtractFromPosField;
            }
            set
            {
                this._ExtractFromPosField = value;
            }
        }

        private string _ExtractToPageField;
        /// <summary></summary>
        public string ExtractToPageField
        {
            get
            {
                return this._ExtractToPageField;
            }
            set
            {
                this._ExtractToPageField = value;
            }
        }

        private string _ExtractToPosField;
        /// <summary></summary>
        public string ExtractToPosField
        {
            get
            {
                return this._ExtractToPosField;
            }
            set
            {
                this._ExtractToPosField = value;
            }
        }

        private string _FlagField;
        /// <summary></summary>
        public string FlagField
        {
            get
            {
                return this._FlagField;
            }
            set
            {
                this._FlagField = value;
            }
        }

        private string _UpdField;
        /// <summary></summary>
        public string UpdField
        {
            get
            {
                return this._UpdField;
            }
            set
            {
                this._UpdField = value;
            }
        }
        #endregion

        #region ctor
        /// <summary></summary>
        public PdfBookmarkExtractionInstruction():base(Guid.Empty, Guid.Empty)
        {
            // src 
            this._SrcConnStr = string.Empty;
            this._SelectSql = string.Empty;
            this._SrcIDField = string.Empty;
            this._FilePathField = string.Empty;

            // bookmark 
            this._BookmarkTitle = string.Empty;
            this._BookmarkPath = string.Empty;
            this._BookmarkSearchPatterns = null;
            this._AcrossMultipleBookmarks = false;
            this._ToBookmarkTitle = string.Empty;
            this._ToBookmarkPath = string.Empty;
            this._ToBookmarkPatterns = null;

            // filter 
            this._ContentFilters=new List<PdfContentFilter>();
            this._UseBoxedContent = false;
            this._MinWidth = 0;
            this._MinHeight = 0;

            // tgt 
            this._TgtConnStr = string.Empty;
            this._TargetTableName = string.Empty;
            this._TgtIDField = string.Empty;
            this._BookmarkContentFieldName = string.Empty;
            this._ExtractFromPageField = string.Empty;
            this._ExtractFromPosField = string.Empty;
            this._ExtractToPageField = string.Empty;
            this._ExtractToPosField = string.Empty;
            this._FlagField = string.Empty;
            this._UpdField = string.Empty;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="componentID"></param>
        /// <param name="jobTicketID"></param>
        /// <param name="srcConnStr"></param>
        /// <param name="selectSql"></param>
        /// <param name="filePathFiled"></param>
        /// <param name="srcIDField"></param>
        /// <param name="title"></param>
        /// <param name="bookmarkPath"></param>
        /// <param name="bookmarkPatterns"></param>
        /// <param name="acrossMultipleBookmarks"></param>
        /// <param name="toBookmarkTitle"></param>
        /// <param name="toBookmarkPath"></param>
        /// <param name="toBookmarkPatterns"></param>
        /// <param name="contentFilters"></param>
        /// <param name="useBoxedContent"></param>
        /// <param name="minW"></param>
        /// <param name="minH"></param>
        /// <param name="tgtConnStr"></param>
        /// <param name="tblName"></param>
        /// <param name="tgtIDField"></param>
        /// <param name="bookmarkContentField"></param>
        /// <param name="fromPageField"></param>
        /// <param name="fromPosField"></param>
        /// <param name="toPageField"></param>
        /// <param name="toPosField"></param>
        /// <param name="flagField"></param>
        /// <param name="updField"></param>
        public PdfBookmarkExtractionInstruction(Guid componentID, Guid jobTicketID,
            string srcConnStr,
            string selectSql,
            string filePathFiled,
            string srcIDField,
            string title,
            string bookmarkPath,
            string[] bookmarkPatterns,
            bool acrossMultipleBookmarks,
            string toBookmarkTitle,
            string toBookmarkPath,
            string[] toBookmarkPatterns,
            List<PdfContentFilter> contentFilters,
            bool useBoxedContent,
            float minW, float minH,
            string tgtConnStr,
            string tblName,
            string tgtIDField,
            string bookmarkContentField,
            string fromPageField,
            string fromPosField, 
            string toPageField,
            string toPosField, 
            string flagField,
            string updField) 
            : base(componentID, jobTicketID)
        {
            this._SrcConnStr = srcConnStr;
            this._SelectSql = selectSql;
            this._FilePathField = filePathFiled;
            this._SrcIDField = srcIDField;

            this._BookmarkTitle = title;
            this._BookmarkPath = bookmarkPath;
            this._BookmarkSearchPatterns = bookmarkPatterns;
            this._AcrossMultipleBookmarks = acrossMultipleBookmarks;
            this._ToBookmarkTitle = toBookmarkTitle;
            this._ToBookmarkPath = toBookmarkPath;
            this._ToBookmarkPatterns = toBookmarkPatterns;

            this._ContentFilters = contentFilters;
            this._UseBoxedContent = useBoxedContent;
            this._MinWidth = minW;
            this._MinHeight = minH;

            this._TgtConnStr = tgtConnStr;
            this._TargetTableName = tblName;
            this._TgtIDField = tgtIDField;
            this._BookmarkContentFieldName = bookmarkContentField;
            this._ExtractFromPageField = fromPageField;
            this._ExtractFromPosField = fromPosField;
            this._ExtractToPageField = toPageField;
            this._ExtractToPosField = toPosField;
            this._FlagField = flagField;
            this._UpdField = updField;
        }
        #endregion

        public override XmlNode Serialize(ref XmlDocument xDoc, ref XmlNode parentNode)
        {
            XmlNode xNode = XmlDataUtil.AddElement(ref xDoc, parentNode, "Instruction");
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "Type", this.GetType().FullName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ComponentID", this.OwnerComponentID.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "WorkerID", this.OwnerWorkerInstanceID.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SubmitTime", this.SubmitTime.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "StartTime", this.StartTime.ToString());

            XmlDataUtil.UpdateAttribute(ref xDoc, xNode,"SrcConnStr",this.SrcConnStr);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SelectSql", this.SelectSql);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "FilePathField", this.FilePathField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SrcIDField", this.SrcIDField);

            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "BookmarkTitle",this.BookmarkTitle);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "BookmarkPath", this.BookmarkPath);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "BookmarkSearchPatterns",
                                        StringUtil.ToString(this.BookmarkSearchPatterns));
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "AcrossMultipleBookmarks",this.AcrossMultipleBookmarks.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ToBookmarkTitle", this.ToBookmarkTitle);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ToBookmarkPath", this.ToBookmarkPath);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ToBookmarkPatterns",
                                        StringUtil.ToString(this.ToBookmarkPatterns));

            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TgtConnStr", this.TgtConnStr);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TgtTable", this.TargetTableName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TgtIDField", this.TgtIDField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "BookmarkContentField", this.BookmarkContentFieldName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "FromPageField",this.ExtractFromPageField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "FromPosField", this.ExtractFromPosField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ToPageField", this.ExtractToPageField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ToPosField", this.ExtractToPosField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "FlagField", this.FlagField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode,"UpdField",this.UpdField);

            if(this.ContentFilters !=null && this.ContentFilters.Count>0)
            {
                XmlNode filterRootNode = XmlDataUtil.AddElement(ref xDoc, xNode, "ContentFilters");
                foreach(PdfContentFilter filter in this.ContentFilters)
                {
                    XmlNode filterNode = XmlDataUtil.AddElement(ref xDoc, filterRootNode, "ContentFilter");
                    XmlDataUtil.UpdateAttribute(ref xDoc, filterNode, "HeaderPattern", filter.HeaderPattern);
                    XmlDataUtil.UpdateAttribute(ref xDoc, filterNode, "FooterPattern", filter.FooterPattern);
                    XmlDataUtil.UpdateAttribute(ref xDoc, filterNode, "SkipHeader",filter.SkipHeader.ToString());
                    XmlDataUtil.UpdateAttribute(ref xDoc, filterNode, "SkipFooter", filter.SkipFooter.ToString());
                }
            }
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "UseBoxedContent", this.UseBoxedContent.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "MinWidth", this.MinWidth.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "MinHeight", this.MinHeight.ToString());
            
            return xNode;
        }

        public override InstructionBase Instantiate(XmlNode xNode)
        {
            if (xNode.Attributes.GetNamedItem("Type").Value == this.GetType().FullName)
            {
                PdfBookmarkExtractionInstruction instruction = new PdfBookmarkExtractionInstruction();
                instruction.OwnerComponentID = new Guid(xNode.Attributes.GetNamedItem("ComponentID").Value);
                instruction.OwnerWorkerInstanceID = new Guid(xNode.Attributes.GetNamedItem("WorkerID").Value);
                instruction.SubmitTime = DateTime.Parse(xNode.Attributes.GetNamedItem("SubmitTime").Value);
                instruction.StartTime = DateTime.Parse(xNode.Attributes.GetNamedItem("StartTime").Value);

                instruction.SrcConnStr = XmlDataUtil.GetAttributeValue(xNode, "SrcConnStr", "");
                instruction.SelectSql = XmlDataUtil.GetAttributeValue(xNode, "SelectSql", "");
                instruction.FilePathField = XmlDataUtil.GetAttributeValue(xNode, "FilePathField", "");
                instruction.SrcIDField = XmlDataUtil.GetAttributeValue(xNode, "SrcIDField", "");

                instruction.BookmarkTitle = XmlDataUtil.GetAttributeValue(xNode, "BookmarkTitle", "");
                instruction.BookmarkPath = XmlDataUtil.GetAttributeValue(xNode, "BookmarkPath", "");
                instruction.BookmarkSearchPatterns =
                    StringUtil.Split(XmlDataUtil.GetAttributeValue(xNode, "BookmarkSearchPatterns", ""));
                instruction.AcrossMultipleBookmarks =
                    bool.Parse(XmlDataUtil.GetAttributeValue(xNode, "AcrossMultipleBookmarks", false.ToString()));
                instruction.ToBookmarkTitle = XmlDataUtil.GetAttributeValue(xNode, "ToBookmarkTitle", "");
                instruction.ToBookmarkPath = XmlDataUtil.GetAttributeValue(xNode, "ToBookmarkPath", "");
                instruction.ToBookmarkPatterns =
                    StringUtil.Split(XmlDataUtil.GetAttributeValue(xNode, "ToBookmarkPatterns", ""));

                XmlNodeList filterNodes = xNode.SelectNodes("ContentFilters/ContentFilter");
                if(filterNodes !=null && filterNodes.Count>0)
                {
                    instruction.ContentFilters=new List<PdfContentFilter>();
                    foreach(XmlNode filterNode in filterNodes)
                    {
                        string headerPattern = XmlDataUtil.GetAttributeValue(filterNode, "HeaderPattern", "");
                        bool skipHeader =
                            bool.Parse(XmlDataUtil.GetAttributeValue(filterNode, "SkipHeader", false.ToString()));
                        string footerPattern = XmlDataUtil.GetAttributeValue(filterNode, "FooterPattern", "");
                        bool skipFooter =
                            bool.Parse(XmlDataUtil.GetAttributeValue(filterNode, "SkipFooter", false.ToString()));
                        PdfContentFilter filter=new PdfContentFilter(headerPattern,skipHeader,footerPattern,skipFooter);
                        instruction.ContentFilters.Add(filter);
                    }
                }
                instruction.UseBoxedContent =
                    bool.Parse(XmlDataUtil.GetAttributeValue(xNode, "UseBoxedContent", false.ToString()));
                instruction.MinWidth =
                    float.Parse(XmlDataUtil.GetAttributeValue(xNode, "MinWidth", "0"));
                instruction.MinHeight =
                    float.Parse(XmlDataUtil.GetAttributeValue(xNode, "MinHeight", "0"));

                instruction.TgtConnStr = XmlDataUtil.GetAttributeValue(xNode, "TgtConnStr", "");
                instruction.TargetTableName = XmlDataUtil.GetAttributeValue(xNode, "TgtTable", "");
                instruction.TgtIDField = XmlDataUtil.GetAttributeValue(xNode, "TgtIDField", "");
                instruction.BookmarkContentFieldName = XmlDataUtil.GetAttributeValue(xNode, "BookmarkContentField", "");
                instruction.ExtractFromPageField = XmlDataUtil.GetAttributeValue(xNode, "FromPageField", "");
                instruction.ExtractFromPosField = XmlDataUtil.GetAttributeValue(xNode, "FromPosField", "");
                instruction.ExtractToPageField = XmlDataUtil.GetAttributeValue(xNode, "ToPageField", "");
                instruction.ExtractToPosField = XmlDataUtil.GetAttributeValue(xNode, "ToPosField", "");
                instruction.FlagField = XmlDataUtil.GetAttributeValue(xNode, "FlagField", "");
                instruction.UpdField = XmlDataUtil.GetAttributeValue(xNode, "UpdField", "");

                return instruction;
            }
            else
            {
                throw new Exception("Unable to instantiate instruction: invalid type specified in xml node");
            }
        }
    }
}
